#ifndef __MQ_CONNECTION_HPP__
#define __MQ_CONNECTION_HPP__

#include "mq_channel.hpp"

namespace mq
{
    class Connection
    {
    public:
        using Ptr = std::shared_ptr<Connection>;

        Connection(const VirtualHost::Ptr& host,
                const ConsumerManager::Ptr cmp,
                const ProtobufCodecPtr& codec,
                const muduo::net::TcpConnectionPtr& conn,
                const threadpool::Ptr& pool)
            :_host(host)
            ,_codec(codec)
            ,_cmp(cmp)
            ,_conn(conn)
            ,_pool(pool)
            ,_channels(std::make_shared<ChannelManager>())
        {
            DLOG("Connection:%p",this);
        }
        // 没有申请的资源。
        // ~Connection();
        void openChannel(const openChannelRequestPtr& req)
        {
            // 1.判断信道ID是否重复。创建信道。
            bool ret = _channels->openChannel(req->cid(),_host,_cmp,_codec,_conn,_pool);
            if(ret == false)
            {
	            DLOG("创建信道的时候，信道ID重复了。");
                
                return basicResponse(false,req->rid(),req->cid());
            }
    	    DLOG("%s创建信道ID成功。",req->cid().c_str());
            // 2.给客户端进行回复。
            return basicResponse(true,req->rid(),req->cid());
        }
        void closeChannel(const closeChannelRequestPtr& req)
        {
            _channels->closeChannel(req->cid());

            return basicResponse(true,req->rid(),req->cid());
        }
        Channel::Ptr getChannel(const std::string& cid)
        {
            Channel::Ptr channel = _channels->choose(cid);

            if(channel.get() == nullptr)
            {
                DLOG("没有找到id:%s的信道",cid.c_str());

                return Channel::Ptr();
            }

            return channel;
        }
    private:
        void basicResponse(bool ok,const std::string& rid,const std::string& cid)
        {
            basicCommonResponse resp;
            resp.set_rid(rid);
            resp.set_cid(cid);
            resp.set_ok(ok);
            _codec->send(_conn,resp);
        }
    private:
        // 虚拟机。
        VirtualHost::Ptr _host;
        // protobuf协议管理。
        ProtobufCodecPtr _codec;
        // 消费者管理。
        ConsumerManager::Ptr _cmp;
        // Tcp网络协议。
        muduo::net::TcpConnectionPtr _conn;
        // 线程池。
        threadpool::Ptr _pool;
        // 信道管理对象
        ChannelManager::Ptr _channels;
    };
    class ConnectionManager
    {
    public:
        using Ptr = std::shared_ptr<ConnectionManager>;
        ConnectionManager(){}
        void newConnection(const VirtualHost::Ptr& host,
                const ConsumerManager::Ptr cmp,
                const ProtobufCodecPtr& codec,
                const muduo::net::TcpConnectionPtr& conn,
                const threadpool::Ptr& pool)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _conns.find(conn);
            if(it != _conns.end())
            {
                DLOG("该链接已经存在了。");
                return ;
            }
            Connection::Ptr connect = std::make_shared<Connection>(host, cmp, codec, conn, pool);
            _conns.insert(std::make_pair(conn,connect));
        }
        void delConnection(const muduo::net::TcpConnectionPtr& conn)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _conns.erase(conn);
        }
        Connection::Ptr getConnection(const muduo::net::TcpConnectionPtr& conn)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _conns.find(conn);
            if(it == _conns.end())
            {
                DLOG("找不到连接。");
                
                return Connection::Ptr();
            }

            return it->second;
        }
    private:
        std::mutex _mutex;
        std::unordered_map<muduo::net::TcpConnectionPtr,Connection::Ptr> _conns;
    };
}

#endif
